package com.sunyard.authorization.service.impl;

import com.sunyard.authorization.service.ManageOperatorService;
import com.sunyard.constant.manage.OperatorConst;
import com.sunyard.constant.manage.StatusConstants;
import com.sunyard.dal.bo.operator.OperatorLoginBO;
import com.sunyard.dal.entity.Operator;
import com.sunyard.dal.entity.OtherParam;
import com.sunyard.dal.entity.Popedom;
import com.sunyard.dal.mapper.*;
import com.sunyard.redisUtil.RedisUtil;
import com.sunyard.utils.manage.DateFormat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 内管登陆接口实现
 */
@Service
public class ManageOperatorServiceImpl implements ManageOperatorService {

    @Autowired
    RedisUtil redisUtil;


    @Autowired
    private OperatorMapper operatorMapper;

    @Autowired
    private PopedomMapper popedomMapper;

    @Autowired
    private OtherParamMapper otherParamMapper;
    /**
     * 超级管理员
     */
    @Value("${admin.name}")
    private String adminName;

    /**
     * 超级审核员
     */
    @Value("${auditor.name}")
    private String auditorName;

    /**
     * 密码错误次数
     */
    @Value("${login.error.count}")
    private String errorCount;

    /**
     * 初始密码
     */
    @Value("${init.pwd}")
    private String initPwd;

    /**
     * 密码错误时间间隔
     */
    @Value("${login.errorTime.rang}")
    private String loginErrorTimeRang;


    @Override
    public void login(HttpServletResponse response,
                      HttpServletRequest request,
                      OperatorLoginBO operatorLoginBO) throws IllegalArgumentException, Exception {
        Operator loginOperator = operatorMapper.getOperatorByOpNameString(operatorLoginBO.getOpName());
        checkAccountStatus(loginOperator);
        //验证用户密码
        if (!loginOperator.getOpPwd().equals(operatorLoginBO.getOpPwd())) {
            dealErrorPwdProcess(loginOperator);
        }
    }

    @Override
    public Operator getOperatorByOpNameString(String opName) {
        return operatorMapper.getOperatorByOpNameString(opName);
    }

    private void dealErrorPwdProcess(Operator loginOperator) throws ParseException {
        //超级管理员登陆失败不计次数
        dealAdminRuleProcess(loginOperator);
        //除了超管和超级审核员之外的角色需要做错误次数处理
        dealNormalRuleProcess(loginOperator);
    }

    private void dealNormalRuleProcess(Operator loginOperator) throws ParseException {
        // 进行密码输入错误次数的统计
        // 设定在30分钟内连续输入5次锁定账户
        Integer loginErrorTimeRangInt = Integer.parseInt(loginErrorTimeRang);
        if (loginErrorTimeRangInt > 0) {
            long timeout = loginErrorTimeRangInt * 60;
            Date beginTime = null;
            if (loginOperator.getOpErrortime() != null && !loginOperator.getOpErrortime().equals("")) {
                beginTime = DateFormat.getDate("yyyy-MM-dd HH:mm:ss", loginOperator.getOpErrortime());
            }
            Date endTime = new Date();
            if (beginTime != null && DateFormat.comPareDate(beginTime, endTime) < timeout) {
                //密码错误次数加1
                loginOperator.setOpPwdErrnum(loginOperator.getOpPwdErrnum() + 1);
                loginOperator.setOpErrortime(DateFormat.dateTimeFormat1(endTime));
            } else {
                loginOperator.setOpPwdErrnum(1);
                loginOperator.setOpErrortime(DateFormat.dateTimeFormat1(endTime));
            }
            //比较密码错误次数
            OtherParam otherParam = otherParamMapper.queryByConfKey(OtherParam.LOGIN_FAIL_TIMES);
            int loginErrorCount = Integer.parseInt(otherParam.getConfValue());
            loginOperator.setUpdateTime(DateFormat.dateTimeFormat1(endTime));
            //设置为空不更新该字段
            loginOperator.setOpLastLoginTime(null);
            if (loginErrorCount > 0 && loginOperator.getOpPwdErrnum() >= loginErrorCount) {
                loginOperator.setOpStatus(Integer.parseInt(StatusConstants.OP_STATUS_LOCKED));
                //更新用户表信息
                operatorMapper.updateOperator(loginOperator);
                throw new IllegalArgumentException("密码输入错误次数超过限制，账户被锁定，请联系管理员解锁");
            } else {
                //更新用户表信息
                operatorMapper.updateOperator(loginOperator);
                throw new IllegalArgumentException("密码输入错误，您还剩" + (loginErrorCount - loginOperator.getOpPwdErrnum()) + "次机会输入正确的密码");
            }
        }
    }

    /**
     * 超级管理员登陆时不处理账号密码错误次数
     *
     * @param loginOperator
     */
    private void dealAdminRuleProcess(Operator loginOperator) {
        if (adminName.equals(loginOperator.getOpName()) || auditorName.equals(loginOperator.getOpName())) {
            throw new IllegalArgumentException("密码错误，请输入正确的用户密码");
        }
    }

    private void checkAccountStatus(Operator loginOperator) {
        if (loginOperator == null) {
            throw new IllegalArgumentException("用户名不存在");
        }
        // 用户状态0：启用 1：停用 2：注销 3：密码锁定
        if (StatusConstants.OPERATPR_LOCK.equals(String.valueOf(loginOperator.getOpStatus()))) {
            throw new IllegalArgumentException(OperatorConst.LOGIN_OP_LOCK_ERROR);
        }
        if (StatusConstants.OPERATPR_LOGOFF.equals(String.valueOf(loginOperator.getOpStatus()))) {
            throw new IllegalArgumentException("账户已经注销，无法登录");
        }
        if (StatusConstants.OPERATPR_DISABLE.equals(String.valueOf(loginOperator.getOpStatus()))) {
            throw new IllegalArgumentException("账户处于停用状态，无法登录");
        }
    }


    /**
     * @Description: 查询登录用户的权限
     * @Author: jiy.fang
     * @Date: 2019/7/30 23:07
     */
    private List<Popedom> getOperatorPopedom(Operator operator) {
        List<Popedom> popedomList = new ArrayList<>();
        List<Popedom> orgPopedoms = popedomMapper.getPopedomByOrgId(operator.getOrgId());
        List<Popedom> rolePopedoms = popedomMapper.getPopedomByRoleId(operator.getRoleId());
        //1
        orgPopedoms.forEach(
                e -> {
                    rolePopedoms.forEach(g -> {
                        if (e.getPopedomId().equals(g.getPopedomId())) {
                            popedomList.add(e);
                        }
                    });
                });
        //2
        for (Popedom orgPopedom : orgPopedoms) {
            for (Popedom rolePopedom : rolePopedoms) {
                if (orgPopedom.getPopedomId().equals(rolePopedom.getPopedomId())) {
                    popedomList.add(orgPopedom);
                }
            }
        }

        return popedomList;
    }

}
